package com.wing.common.utils;

import org.apache.commons.lang.StringUtils;

import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 日期处理工具类
 */
public class DateUtils {

    /**
     * 时间格式(yyyyMMdd)
     */
    public final static String DATE_PATTERN_FORMAT = "yyyyMMdd";

    /**
     * 时间格式(yyyyMM)
     */
    public final static String DATE_PATTERN_FORMAT_MONTH2 = "yyyyMM";

    /**
     * 时间格式(yyyy-MM)
     */
    public final static String DATE_PATTERN_FORMAT_MONTH = "yyyy-MM";

    /**
     * 时间格式(mm:ss)
     */
    public final static String DATE_PATTERN_FORMAT_MMSS = "mm:ss";

    /**
     * 时间格式(yyyy-MM-dd)
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";

    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public final static String DATE_TIME_PATTERN_ = "HH:mm:ss";

    /**
     * DCS点位记录时间格式
     */
    public final static String DATE_TIME_PATTERN_ONE = "yyyyMMddHHmm";

    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    public static Date stringFormatDate(String date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            try {
                return df.parse(date);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static String formatSecond(Date date, Integer second) {
        if (date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.SECOND, -second);
            SimpleDateFormat df = new SimpleDateFormat(DATE_TIME_PATTERN_);
            return df.format(calendar.getTime());
        }
        return null;
    }

    /**
     * 获取某个时间点后的分钟时间
     */
    public static String format(Date date, Integer minute) {
        if (date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.MINUTE, minute);
            SimpleDateFormat df = new SimpleDateFormat(DATE_TIME_PATTERN);
            return df.format(calendar.getTime());
        }
        return null;
    }

    /**
     * 获取某个时间点后的小时
     */
    public static Date formatHour(Date date, Integer hours) {
        if (date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.HOUR, hours);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 获取某个时间点后的天数
     */
    public static Date formatDay(Date date, Integer day) {
        if (date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DAY_OF_YEAR, day);
            return calendar.getTime();
        }
        return null;
    }

    public static Date formatMonth(Date date, Integer month) {
        if (date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.MONTH, month);
            return calendar.getTime();
        }
        return null;
    }

    public static Date getLastMonthDate(Date date) {
        if (date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.MONTH, -1);
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            return calendar.getTime();
        }
        return null;
    }


    /**
     * 计算距离现在多久，非精确
     *
     * @param date
     * @return
     */
    public static String getTimeBefore(Date date) {
        Date now = new Date();
        long l = now.getTime() - date.getTime();
        long day = l / (24 * 60 * 60 * 1000);
        long hour = (l / (60 * 60 * 1000) - day * 24);
        long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        String r = "";
        if (day > 0) {
            r += day + "天";
        } else if (hour > 0) {
            r += hour + "小时";
        } else if (min > 0) {
            r += min + "分";
        } else if (s > 0) {
            r += s + "秒";
        }
        r += "前";
        return r;
    }

    /**
     * 计算距离现在多久，精确
     *
     * @param date
     * @return
     */
    public static String getTimeBeforeAccurate(Date date) {
        Date now = new Date();
        long l = now.getTime() - date.getTime();
        long day = l / (24 * 60 * 60 * 1000);
        long hour = (l / (60 * 60 * 1000) - day * 24);
        long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        String r = "";
        if (day > 0) {
            r += day + "天";
        }
        if (hour > 0) {
            r += hour + "小时";
        }
        if (min > 0) {
            r += min + "分";
        }
        if (s > 0) {
            r += s + "秒";
        }
        r += "前";
        return r;
    }

    /**
     * 计算两个时间点间隔的天数
     */
    public static int getTimeDay(String startDate, String endDate) {
        SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN);
        try {
            BigInteger begin = BigInteger.valueOf(df.parse(startDate).getTime());
            BigInteger end = BigInteger.valueOf(df.parse(endDate).getTime());
            BigInteger days = (end.subtract(begin)).divide(new BigInteger("1000")).divide(new BigInteger("60")).divide(new BigInteger("60")).divide(new BigInteger("24"));
            return days.compareTo(BigInteger.ZERO) == 0 ? 1 : days.intValue();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 计算两个时间点间隔的分钟数
     */
    public static int getTimeMin(String startDate, String endDate) {
        SimpleDateFormat df = new SimpleDateFormat(DATE_TIME_PATTERN);
        try {
            long begin = df.parse(startDate).getTime();
            long end = df.parse(endDate).getTime();
            return (int) ((int) (end - begin) / (1000 * 60) == 0 ? 1 : (end - begin) / (1000 * 60));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 计算两个时间点间隔的秒钟数
     */
    public static int getTimeSecond(String startDate, String endDate) {
        SimpleDateFormat df = new SimpleDateFormat(DATE_TIME_PATTERN);
        try {
            long begin = df.parse(startDate).getTime();
            long end = df.parse(endDate).getTime();
            return (int) (end - begin) / 1000;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 计算两个时间点间隔的毫秒输
     */
    public static int getTimeMilliSecond(String startDate, String endDate) {
        SimpleDateFormat df = new SimpleDateFormat(DATE_TIME_PATTERN);
        try {
            long begin = df.parse(startDate).getTime();
            long end = df.parse(endDate).getTime();
            return (int) (end - begin);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 如果格式错误就返回当前系统时间
     *
     * @param dateValue
     * @param pattern
     * @return
     */
    public static Date stringToDate(String dateValue, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try {
            return sdf.parse(dateValue);
        } catch (ParseException e) {
            return new Date();
        }
    }

    // 获取前一天的时间,格式 yyyy-MM-dd
    public static String getBeforeDate(Date date) {
        Calendar ca = Calendar.getInstance();// 得到一个Calendar的实例
        ca.setTime(date); // 设置时间为当前时间
        ca.add(Calendar.DAY_OF_YEAR, -1);
        Date day = ca.getTime(); // 结果
        return DateUtils.format(day, DATE_PATTERN);
    }

    /**
     * 获取当前时间前后日期
     *
     * @param date 日期
     * @param dayNum  天数
     * @return
     */
    public static String getDateByDay(Date date, Integer dayNum) {
        Calendar ca = Calendar.getInstance();// 得到一个Calendar的实例
        ca.setTime(date); // 设置时间为当前时间
        ca.add(Calendar.DAY_OF_YEAR, dayNum);
        Date day = ca.getTime(); // 结果
        return DateUtils.format(day, DATE_PATTERN);
    }

    public static Date getStartOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getEndOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    public static Long timeStampToUint32(Long timestamp) {
        Long seconds = timestamp / 1000;
        Long result = seconds % (1L << 32);
        return result;
    }

    public static LocalDateTime convertToLocalDateTime(String dateStr) {
        if(StringUtils.isNotEmpty(dateStr)){
            // 提取年份、月份和日期
            int year = extractDatePart(dateStr, 0);
            int month = extractDatePart(dateStr, 1);
            int day = extractDatePart(dateStr, 2);

            // 构造 LocalDateTime 对象，时间部分默认设置为 00:00:00
            return LocalDateTime.of(year, month, day, 0, 0, 0, 0);
        }else {
            return null;

        }

    }

    private static int extractDatePart(String dateStr, int partIndex) {
        // 使用正则表达式提取年份、月份和日期，支持 1 位或 2 位数
        Pattern pattern = Pattern.compile("(\\d{1,4})");
        Matcher matcher = pattern.matcher(dateStr);

        int index = 0;
        while (matcher.find()) {
            if (index == partIndex) {
                return Integer.parseInt(matcher.group());
            }
            index++;
        }

        // 如果没找到对应部分，抛出异常
        throw new IllegalArgumentException("Could not extract date part at index: " + partIndex + " from " + dateStr);
    }

    public static void main(String[] args) {
        System.out.println(format(formatDay(stringFormatDate("2021-01-15 00:00:00", DATE_TIME_PATTERN), 75), DATE_TIME_PATTERN));

        System.out.println(format(formatMonth(new Date(), -1)));
//		System.out.println(format(StringformatDate("2021/01/30 23:59:50", DATE_TIME_PATTERN)).equals(format(new Date())));


        // System.out.println(format(new Date(), -125));
        // System.out.println(format(new Date(), -115));
        // System.out.println(formatHour(new Date(), 10));
        // System.out.println(getTimeMilliSecond(format(new Date(),
        // DATE_TIME_PATTERN), getUpdateMerchantXfReportTime()));
        // System.out.println(format(new Date(), DATE_PATTERN_FORMAT_MONTH));
        // System.out.println(stringToDate("20190827113323",DATE_TIME_PATTERN));

        // System.out.println(DateUtils.StringformatDate(DateUtils.format(new
        // Date(), DateUtils.DATE_PATTERN), DateUtils.DATE_TIME_PATTERN));

        String queryTime = "2024-10";

        Date startOfMonth = getStartOfMonth(new Date());
        Date endOfMonth = getEndOfMonth(new Date());

        System.out.println("月初: " + startOfMonth);
        System.out.println("月末: " + endOfMonth);

        System.out.println("月初: " + format(startOfMonth, DATE_PATTERN));
        System.out.println("月末: " + format(endOfMonth, DATE_PATTERN));

        System.out.println("月初: " + DateUtils.timeStampToUint32(DateUtils.getStartOfMonth(new Date()).getTime()));
        System.out.println("月末: " + DateUtils.timeStampToUint32(DateUtils.getStartOfMonth(new Date()).getTime()));

        System.out.println("当前时间: " + getDateByDay(new Date(), 0));
        System.out.println("当前时间: " + getDateByDay(new Date(), -6));

        System.out.println("间隔天数: " + getTimeDay("2024-12-30", "2024-12-30"));
        System.out.println("间隔天数: " + getTimeDay(getDateByDay(new Date(), -6), getDateByDay(new Date(), 0)));

        //格林威治时间转换
        System.out.println();

        String gmt_date = "1647930683063";


        System.out.println(Long.MAX_VALUE);

        System.out.println(format(new Date(1647930683063L),DATE_TIME_PATTERN));

        System.out.println(stringFormatDate(gmt_date, DATE_TIME_PATTERN));

        System.out.println("-------------------------------------");
        LocalDateTime start = LocalDateTime.of(2024, 2, 9, 7, 0, 0); // 2024-02-08 07:00
        LocalDateTime end = LocalDateTime.of(2024, 2, 9, 8, 0, 0);   // 2024-02-09 08:00

        System.out.println("账单天数: " + calculateDateInterval(start, end)); // 结果: 1
    }

    public static String getYearMonth() {
        return format(new Date(), DATE_PATTERN_FORMAT_MONTH);
    }

    public static String getLastMonth() {
        // 使用 Calendar 获取当前日期
        Calendar calendar = Calendar.getInstance();
        // 将月份减1，注意：Calendar 会自动处理跨年情况
        calendar.add(Calendar.MONTH, -1);
        // 使用已有的格式化方法进行格式化
        return format(calendar.getTime(), DATE_PATTERN_FORMAT_MONTH);
    }



    /**
     * 计算存储天数（忽略小时、分钟、秒，入库当天算 1 天）
     * @param startDateTime 入库时间（包含）
     * @param endDateTime 结算时间（不包含）
     * @return 计算的天数（同一天不计入天数）
     */
    public static int calculateDateInterval(LocalDateTime startDateTime, LocalDateTime endDateTime) {
        if (startDateTime == null || endDateTime == null || !endDateTime.isAfter(startDateTime)) {
            return 0; // 无效日期，返回 0
        }

        // 转换为 LocalDate（去掉时间部分）
        LocalDate startDate = startDateTime.toLocalDate();
        LocalDate endDate = endDateTime.toLocalDate();

        // 如果入库日期和结束日期是同一天，不计算天数
        if (startDate.equals(endDate)) {
            return 0;
        }

        // 计算天数差
        int days = (int) ChronoUnit.DAYS.between(startDate, endDate);

        return days + 1; // 入库当天算 1 天，所以 +1
    }
}
